#ifndef _CLASSOBJECT_H_
#define _CLASSOBJECT_H_

#include "string"
#include "singleton.hpp"
#include "classFactory.h"
#include "functional"

using namespace std;

class ClassField;

class ClassFactory;

class ClassObject
{
public:
    template<class T>
    bool get(const string fieldName, T & value);

    template<class T>
    bool set(const string fieldName, const T & value);

    bool call(const string & methodName);

public:
    string m_className;

};

template<class T>   
bool ClassObject::get(const string fieldName, T & value)
{
    ClassField * field = reflect::Singleton<ClassFactory>::getInstance().getClassFieldFromName(m_className);
    if(field == nullptr) 
    {
        return false;
    }
    size_t offset = field->getOffsetFromFieldName(fieldName);
    if(offset == (size_t)-1) return false;
    value = *(T*)((char*)this + offset);
    return true;
}

template<class T>
bool ClassObject::set(const string fieldName, const T & value)
{
    ClassField * field = reflect::Singleton<ClassFactory>::getInstance().getClassFieldFromName(m_className);
    if(field == nullptr) 
    {
        return false;
    }
    size_t offset = field->getOffsetFromFieldName(fieldName);
    if(offset == (size_t)-1) return false;
    *(T*)((char*)this + offset) = value;
    return true;
}




#define RIGISTERCLASS(className)\
    ClassObject * create##className()\
    {\
        return new className;\
    }\
    ClassRegister register##className(#className, create##className);\

#define RIGISTERCLASSFIELD(className, fieldName)\
    className class##className##fieldName;\
    size_t offset##className##fieldName = (size_t)&class##className##fieldName.fieldName - (size_t)&class##className##fieldName;\
    ClassRegister registerField##className##fieldName(#className, #fieldName, offset##className##fieldName);\

#define RIGISTERCLASSMETHOD(className, methodName)\
    typedef function<void(className*)> method##className##methodName;\
    method##className##methodName m##className##methodName = &className::methodName;\
    size_t funcptr##className##methodName = (size_t)&m##className##methodName;\
    ClassRegister registerMethod##className##methodName(#className, #methodName, funcptr##className##methodName, true);\

#endif
